Post

Replies

Boosts

Views

Activity

Reply to PHImageManager Error
I appreciate your revert Claudia, I set targetSize constant as an optional to solve the error but it didn't work. I ran your proposed code, I got the same error message on line 04 "targetSize". Then, I set a breakpoint on line 04 "targetSize" and after I stepped into it, the error pointed out the "photoImageView" outlet.
Mar ’20
Reply to PHImageManager Error
Sure, here are the logs; (this time the error is on "print("photoImageView", photoImageView)" Regarding this viewController, on the same photoImageView outlet, I also access my photo library from the previous viewController without any error. I've been having trouble with accessing the latest photo in the library as the log prints photoImageView as nil. 2020-03-22 17:34:31.197852+0300 Stitch[60446:1861363] [Warning] Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a table view cell's content view. We're considering the collapse unintentional and using standard height instead. Cell: <Stitch.PhotoPopUpCell: 0x7ff73c89c5a0; baseClass = UITableViewCell; frame = (0 0; 341.667 44); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x6000029609c0>>photoImageView nilFatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/sedatonurduzova/Desktop/Xcode Projects/iOS Photos Framework/Manipulate Assets to Generate Collages/P02E04 Observe Photo Library Changes to Update UI/end/Stitch/Effect View Controllers/PhotoViewController.swift, line 672020-03-22 17:34:39.737915+0300 Stitch[60446:1861363] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/sedatonurduzova/Desktop/Xcode Projects/iOS Photos Framework/Manipulate Assets to Generate Collages/P02E04 Observe Photo Library Changes to Update UI/end/Stitch/Effect View Controllers/PhotoViewController.swift, line 67(lldb)
Mar ’20
Reply to PHImageManager Error
My previous message with the full logs is being moderated. This time the error is on "print("photoImageView", photoImageView)" Regarding this viewController, on the same photoImageView outlet, I also access my photo library from the previous viewController without any error. I've been having trouble with accessing the latest photo in the library as the log prints photoImageView as nil.photoImageView nilFatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file
Mar ’20
Reply to PHImageManager Error
I apologise, you are right the error is on line 05; print("photoImageView.bounds", photoImageView.bounds)The complete PhotoViewController;import Foundationimport UIKitimport Photosclass PhotoViewController: UIViewController { @IBOutlet weak var photoImageView: UIImageView! var imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self } func chooseImage(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = true self.present(imagePicker,animated: true, completion: nil) } } func accessVideo(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.camera) { imagePicker.sourceType = .camera self.present(imagePicker, animated: true, completion: nil) } else { print("Camera not available") } } public func chooseLastImage(_ sender: Any) { let scale = UIScreen.main.scale print("photoImageView", photoImageView) print("photoImageView.bounds", photoImageView.bounds) let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width * scale, height: photoImageView.bounds.height * scale) print("targetSize", targetSize) // Is it nil ? If not, what is its value let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"lastCreationDate", ascending: true)] let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: (.image), options: fetchOptions) print("targetSize for request", targetSize) //What is its value imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result }) } } }extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { photoImageView.image = image } dismiss(animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) }}
Mar ’20
Reply to PHImageManager Error
I've taken the steps you have suggested, the same error continues on the same line. The viewController calling the function;import Foundationimport UIKitimport Photosclass PhotoPopUpViewController: UIViewController { let photoViewController = PhotoViewController() override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { dismiss(animated: true, completion: nil) } @IBOutlet private var photoCollectionView: UICollectionView! @IBOutlet weak var tableView: UITableView! var imageArray = [UIImage]() var tableImages: [PhotoPopUpCellData] = [] var selectedTableImage: PhotoPopUpCellData? override func viewDidLoad() { super.viewDidLoad() grabPhotos() tableImages = createArray() tableView.delegate = self tableView.dataSource = self } func grabPhotos() { let imgManager = PHImageManager.default() let requestOptions = PHImageRequestOptions() requestOptions.isSynchronous = true requestOptions.deliveryMode = .highQualityFormat let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] let fetchResult: PHFetchResult<PHAsset> = PHAsset.fetchAssets(with: .image, options: fetchOptions) if fetchResult.count > 0 { for i in 0..<fetchResult.count { imgManager.requestImage(for: fetchResult.object(at: i), targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: { image, error in self.imageArray.append(image!) }) } } else { print("You got no photos!") } }}extension PhotoPopUpViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return imageArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoPopUpCell", for: indexPath) as? DataCollectionViewCell cell?.img.image = imageArray[indexPath.row] return cell! }}extension PhotoPopUpViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = collectionView.bounds.width / 3.0 let height = collectionView.bounds.height return CGSize(width: width, height: height) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 1 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 1 }}extension PhotoPopUpViewController { func createArray() -> [PhotoPopUpCellData] { var tempData: [PhotoPopUpCellData] = [] let tableImages1 = PhotoPopUpCellData(image: UIImage(systemName: "photo")!, title: "Open from Albums") let tableImages2 = PhotoPopUpCellData(image: UIImage(systemName: "camera.fill")!, title: "Take a Photo") let tableImages3 = PhotoPopUpCellData(image: UIImage(systemName: "tray.and.arrow.up.fill")!, title: "Open last Image") tempData.append(tableImages1) tempData.append(tableImages2) tempData.append(tableImages3) return tempData }}extension PhotoPopUpViewController: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return tableImages.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let tableImage = tableImages[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: "PhotoPopUpCell") as! PhotoPopUpCell cell.setPhotoPopUp(photoPopUpCellData: tableImage) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let tableImage = tableImages[indexPath.row] selectedTableImage = tableImage if indexPath.row == 0 { present(photoViewController, animated: false, completion: { self.photoViewController.chooseImage(self) }) } if indexPath.row == 1 { present(photoViewController, animated: false, completion: { self.photoViewController.accessVideo(self) }) } if indexPath.row == 2 { present(photoViewController, animated: false, completion: { self.photoViewController.chooseLastImage(self) }) } }}
Mar ’20
Reply to Accessing another viewController's image from CustomCell Class
Now, I get an empty collectionView. I guess the only way to make this work is;class CustomCell: UICollectionViewCell { var photoViewController: PhotoViewController? fileprivate let bg: UIImageView = { let iv = UIImageView() iv.image = ? iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFill iv.clipsToBounds = true return iv }()My new code;import Foundationimport UIKitimport Photosclass PhotoViewController: UIViewController { @IBOutlet weak var photoImageView: UIImageView! @IBOutlet weak var peeTabBar: UITabBar! @IBOutlet var photoView: UIView! var imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self assignTap() view.addSubview(collectionView) collectionView.backgroundColor = .white collectionView.topAnchor.constraint(equalTo: photoImageView.bottomAnchor, constant: 110).isActive = true collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true collectionView.bottomAnchor.constraint(equalTo: peeTabBar.topAnchor, constant: -20).isActive = true collectionView.delegate = self collectionView.dataSource = self } func assignTap() { let tap = UITapGestureRecognizer(target: self, action: #selector(touchTapped(_:))) photoView.addGestureRecognizer(tap) } @objc func touchTapped(_ sender: UITapGestureRecognizer) { peeTabBar.isHidden = !peeTabBar.isHidden } func chooseImage(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = true self.present(imagePicker,animated: true, completion: nil) } } func accessVideo(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.camera) { imagePicker.sourceType = .camera self.present(imagePicker, animated: true, completion: nil) } else { print("Camera not available") } } public func chooseLastImage(_ sender: Any) { print("photoImageView", photoImageView!) print("photoImageView.bounds", photoImageView.bounds) let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height) let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) print("targetSize for request", targetSize!) //What is its value imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result }) } } fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell") return cv }()}extension PhotoViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width/5, height: collectionView.frame.width/5) } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 11 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell cell.photoViewController = self return cell }}class CustomCell: UICollectionViewCell { var photoViewController: PhotoViewController? fileprivate let bg: UIImageView = { let iv = UIImageView() iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFill iv.clipsToBounds = true return iv }() override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(bg) bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }}extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { photoImageView.image = image } dismiss(animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) }}
Mar ’20
Reply to Accessing another viewController's image from CustomCell Class
I get the following error "Instance member 'photoViewController' cannot be used on type 'CustomCell'"class CustomCell: UICollectionViewCell { var photoViewController: PhotoViewController? fileprivate let bg: UIImageView = { let iv = UIImageView(image: photoViewController?.photoImageView.image) iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFill iv.clipsToBounds = true return iv }()
Mar ’20
Reply to Prototype collection view section header or footer views must have reuse identifiers
import Foundationimport UIKitimport Photosclass PhotoViewController: UIViewController { @IBOutlet weak var photoImageView: UIImageView! @IBOutlet var photoView: UIView! @IBOutlet weak var menuStackView: UIStackView! var imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self assignTap() view.addSubview(collectionView) collectionView.backgroundColor = .white collectionView.topAnchor.constraint(equalTo: photoImageView.bottomAnchor, constant: 110).isActive = true collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 10).isActive = true collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -103).isActive = true collectionView.clipsToBounds = true collectionView.dataSource = self collectionView.delegate = self collectionView.isHidden = false } @IBAction func previewTapped(_ sender: UIButton) { sender.pulsate() if collectionView.isHidden == true { collectionView.isHidden = false } else { collectionView.isHidden = true } } @IBAction func effectsTapped(_ sender: UIButton) { sender.flash() } @IBAction func exportTapped(_ sender: UIButton) { sender.shake() } func assignTap() { let tap = UITapGestureRecognizer(target: self, action: #selector(touchTapped(_:))) photoView.addGestureRecognizer(tap) } @objc func touchTapped(_ sender: UITapGestureRecognizer) { if menuStackView.isHidden == false { collectionView.isHidden = true menuStackView.isHidden = true } else { menuStackView.isHidden = false collectionView.isHidden = false } } func chooseImage(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = true self.present(imagePicker,animated: true, completion: nil) } } func accessVideo(_ sender: Any) { if UIImagePickerController.isSourceTypeAvailable(.camera) { imagePicker.sourceType = .camera self.present(imagePicker, animated: true, completion: nil) } else { print("Camera not available") } } public func chooseLastImage(_ sender: Any) { print("photoImageView", photoImageView!) print("photoImageView.bounds", photoImageView.bounds) let targetSize: CGSize? = CGSize(width: photoImageView.bounds.width, height: photoImageView.bounds.height) let options = PHImageRequestOptions() options.isNetworkAccessAllowed = true options.deliveryMode = .highQualityFormat let imgManager = PHImageManager.default() let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)] let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) print("targetSize for request", targetSize!) //What is its value imgManager.requestImage(for: fetchResult.lastObject!, targetSize: targetSize!, contentMode: .default, options: options) { (result, info) in guard let result = result else { return } DispatchQueue.main.async(execute: { self.photoImageView.image = result self.collectionView.reloadData() }) } } fileprivate let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.translatesAutoresizingMaskIntoConstraints = false cv.register(CustomCell.self, forCellWithReuseIdentifier: "PreviewCell") cv.register(CustomCell.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "FooterCell") return cv }()}extension PhotoViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: collectionView.frame.width/5, height: collectionView.frame.width/4) } func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionFooter { let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FooterCell", for: indexPath) as! CustomCell footer.backgroundColor = .blue return footer } else { assert(false, "Unexpected element kind") } } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 11 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewCell", for: indexPath) as! CustomCell DispatchQueue.main.async { cell.bgImage = self.photoImageView.image } return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 1 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: view.frame.width, height: 10) }}class CustomCell: UICollectionViewCell { fileprivate let bg: UIImageView = { let iv = UIImageView() iv.translatesAutoresizingMaskIntoConstraints = false iv.contentMode = .scaleAspectFit iv.clipsToBounds = true return iv }() var bgImage: UIImage? { get { bg.image } set { bg.image = newValue } } override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(bg) bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true }required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }}extension PhotoViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { photoImageView.image = image } dismiss(animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) }}
Apr ’20